Development FAQ
The following is a list of Frequently Asked Questions (FAQs), with answers, and notes related to development using LibPurple. (Note for developers: There needs to be an easy way to linkify the functions names below to our doxygen documentations.
Accounts
I created an account, but it's not being saved!
You need to use purple_accounts_add()
to add the account to the list of available accounts. This list of accounts is saved. Note that many of the functions require an account to be on that list. So you should always call purple_accounts_add()
after creating an account.
How do I get online with an account?
There are two ways you can do this:
- If you have other accounts online, and you want the new account to have the same status as those, then call
purple_savedstatus_get_current()
to get the current status, and usepurple_savedstatus_activate_for_account()
for the account. - Otherwise, you can simply do
purple_account_set_status()
to set the status of the account.
An account needs to be enabled before it can be connected. So after doing either of the above, you need to enable the account by calling purple_account_set_enabled()
.
Conversations
How can I create a conversation with someone?
Use purple_conversation_new()
. Use PURPLE_CONV_TYPE_IM
if the conversation is an IM (one-to-one person conversation), and use PURPLE_CONV_TYPE_CHAT
if it's a multi-user conversation. One important thing to note here is that the name property of the PurpleConversation
struct is the name of the buddy you are creating a conversation with (the documentation states that this is the name of the conversation itself, but it is in fact also the name of the receiving buddy). So a call to purple_conversation_new()
takes the name of the buddy as its third argument.
How can I send a message in a conversation?
Use either purple_conv_im_send()
or purple_conv_chat_send()
. Note that the first parameter to either of these functions are not the conversation itself. Rather, it's the IM data or chat data of the conversation which you can get from PURPLE_CONV_IM
/PURPLE_CONV_CHAT
.
Is there a way that I can print something in the conversation window, but not send the message?
Yes. Use purple_conv_im_write()
or purple_conv_chat_write()
.
Files and File Paths
What do I do with DATADIR
, LOCALEDIR
, and LIBDIR
?
DATADIR
, LOCALEDIR
, and LIBDIR
are defined as functions in the Windows build. Therefore, doing something like this will break the Windows build:
printf("File in DATADIR is: %s\n", DATADIR G_DIR_SEPARATOR_S "pic.png")
Instead, it should be:
printf("File in DATADIR is: %s%s%s\n", DATADIR, G_DIR_SEPARATOR_S, "pic.png");
Why are files opened with mode b
?
Without this, on Windows systems the opened files will use Windows default translation (<CR><LF> for newline, for example). This will cause errors due to newline format and the "bytes read" counts, which will be wrong when comparing the return value of read()
to stat()
.
Why are G_DIR_SEPARATOR_S
and G_DIR_SEPARATOR
used everywhere?
This is a matter of maintaining cross-platform compatibility. Windows uses a backslash ("\") for directory separators in paths, while UNIX-like systems use the forward slash ("/"). Other OSes may choose to use other separators--for example, prior to Mac OS X, it was common for the directory separator on Macs to be a colon (":"). It is impractical to use preprocessor directives throughout the code to determine the path style to use, especially if a new OS were to appear and use a different directory separator. GLib, which we already use, provides the convenient separator macro, so we use this to reduce our code complexity and maintain cross-platform portability.
General
What should I do to get the contents of an environment variable?
Use g_getenv()
.
Should I use snprintf()
or vsnprintf()
?
No. Use the GLib wrapper functions instead. They are g_snprintf()
and g_vsnprintf()
.
How do I get the settings directory?
Use purple_home_dir()
. You should not use g_get_home_dir()
or getenv("HOME")
.
What is the versioning scheme?
There are three fields in the version: major.minor.micro
.
- If the
major
is changing, you can break plugins. That means both forward- and backward- compatibility. API can be added or removed or whatever you like. - If only the
minor
is changing, you can break forward compatibility only. You may add API, but you can't remove it. You can mark API as deprecated instead. - If only the
micro
is changing, you can't break the API at all.
Headers
Why is win32dep.h causing problems for me?
You need to make sure it is the last header you include if you need to include it. Not doing so is asking for problems.
Plugins and Protocols
How should I handle global variables?
Use G_MODULE_IMPORT
for any global variable located outside your dynamic library. Not doing this will cause "Memory Access Violation" errors on Windows systems.
What should I do for "exported" functions?
If your plugin has functions that are to be accessed from outside the scope of its file (.dll or .so), G_MODULE_EXPORT
those functions.